<template>
  <div class="min-h-screen py-8 px-4 sm:px-6 lg:px-8">
    <div class="max-w-7xl mx-auto">
      <!-- 页面标题 -->
      <div class="text-center mb-12">
        <h1 class="text-4xl font-bold mb-4 tech-text">Web MIDI API</h1>
        <p class="text-gray-300 text-lg">
          连接和控制 MIDI 设备，实现音乐创作和演奏功能
        </p>
      </div>

      <!-- 浏览器支持提示 -->
      <div v-if="!isSupported" class="tech-card mb-8 border-yellow-600">
        <div class="flex items-center mb-4">
          <i class="i-carbon-warning text-yellow-500 text-xl mr-3"></i>
          <h3 class="text-xl font-semibold text-yellow-500">浏览器支持提示</h3>
        </div>
        <p class="text-gray-300">
          您的浏览器不支持 Web MIDI API。此功能需要 Chrome 43+、Edge 79+ 或 Opera 30+。
        </p>
      </div>

      <!-- 权限请求 -->
      <div v-if="isSupported && !midiAccess" class="tech-card mb-8">
        <div class="text-center py-8">
          <i class="i-carbon-piano text-6xl text-gray-600 mb-4 block"></i>
          <h3 class="text-2xl font-semibold text-white mb-4">请求 MIDI 访问权限</h3>
          <p class="text-gray-300 mb-6">
            需要访问您的 MIDI 设备才能使用此功能
          </p>
          <button
            @click="requestMIDIAccess"
            :disabled="isRequesting"
            class="tech-button disabled:opacity-50 disabled:cursor-not-allowed"
          >
            <i class="i-carbon-connection-signal mr-2"></i>
            {{ isRequesting ? '请求中...' : '请求访问权限' }}
          </button>
          <p v-if="accessError" class="text-red-400 mt-4">{{ accessError }}</p>
        </div>
      </div>

      <template v-if="midiAccess">
        <!-- MIDI 设备列表 -->
        <div class="tech-card mb-8">
          <h2 class="text-2xl font-semibold mb-6 text-white">MIDI 设备</h2>
          
          <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
            <!-- 输入设备 -->
            <div class="bg-gray-800 rounded-lg p-6">
              <div class="flex items-center mb-4">
                <i class="i-carbon-keyboard text-2xl text-blue-400 mr-3"></i>
                <h3 class="text-xl font-semibold text-white">输入设备 ({{ inputDevices.length }})</h3>
              </div>
              
              <div v-if="inputDevices.length === 0" class="text-gray-400 text-center py-4">
                未检测到 MIDI 输入设备
              </div>
              
              <div v-else class="space-y-3">
                <div
                  v-for="device in inputDevices"
                  :key="device.id"
                  class="bg-gray-900 rounded-lg p-4"
                >
                  <div class="flex items-start justify-between mb-2">
                    <div class="flex-1">
                      <h4 class="text-white font-semibold">{{ device.name }}</h4>
                      <p class="text-gray-400 text-sm">{{ device.manufacturer || '未知制造商' }}</p>
                    </div>
                    <span
                      :class="[
                        device.state === 'connected' 
                          ? 'bg-green-600' 
                          : 'bg-gray-600',
                        'px-2 py-1 rounded text-xs text-white'
                      ]"
                    >
                      {{ device.state === 'connected' ? '已连接' : '已断开' }}
                    </span>
                  </div>
                  <div class="text-gray-500 text-xs">
                    ID: {{ device.id }}
                  </div>
                </div>
              </div>
            </div>

            <!-- 输出设备 -->
            <div class="bg-gray-800 rounded-lg p-6">
              <div class="flex items-center mb-4">
                <i class="i-carbon-music text-2xl text-purple-400 mr-3"></i>
                <h3 class="text-xl font-semibold text-white">输出设备 ({{ outputDevices.length }})</h3>
              </div>
              
              <div v-if="outputDevices.length === 0" class="text-gray-400 text-center py-4">
                未检测到 MIDI 输出设备
              </div>
              
              <div v-else class="space-y-3">
                <div
                  v-for="device in outputDevices"
                  :key="device.id"
                  class="bg-gray-900 rounded-lg p-4"
                >
                  <div class="flex items-start justify-between mb-2">
                    <div class="flex-1">
                      <h4 class="text-white font-semibold">{{ device.name }}</h4>
                      <p class="text-gray-400 text-sm">{{ device.manufacturer || '未知制造商' }}</p>
                    </div>
                    <span
                      :class="[
                        device.state === 'connected' 
                          ? 'bg-green-600' 
                          : 'bg-gray-600',
                        'px-2 py-1 rounded text-xs text-white'
                      ]"
                    >
                      {{ device.state === 'connected' ? '已连接' : '已断开' }}
                    </span>
                  </div>
                  <div class="text-gray-500 text-xs mb-3">
                    ID: {{ device.id }}
                  </div>
                  <button
                    @click="selectOutputDevice(device)"
                    :class="[
                      selectedOutput?.id === device.id
                        ? 'bg-tech-accent'
                        : 'bg-gray-700 hover:bg-gray-600',
                      'text-white px-4 py-2 rounded text-sm w-full transition-colors'
                    ]"
                  >
                    {{ selectedOutput?.id === device.id ? '已选择' : '选择此设备' }}
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- MIDI 消息监视器 -->
        <div class="tech-card mb-8">
          <div class="flex items-center justify-between mb-6">
            <h2 class="text-2xl font-semibold text-white">MIDI 消息监视器</h2>
            <button
              @click="clearMessages"
              class="text-red-400 hover:text-red-300 text-sm"
            >
              <i class="i-carbon-clean mr-1"></i>
              清空
            </button>
          </div>
          
          <div class="bg-gray-800 rounded-lg p-6 h-64 overflow-y-auto">
            <div v-if="midiMessages.length === 0" class="text-gray-400 text-center py-8">
              等待 MIDI 消息...
            </div>
            
            <div v-else class="space-y-2 font-mono text-sm">
              <div
                v-for="(msg, index) in midiMessages.slice().reverse()"
                :key="index"
                class="flex items-start gap-3 text-gray-300"
              >
                <span class="text-gray-500">{{ msg.timestamp }}</span>
                <span
                  :class="[
                    msg.type === 'noteon' ? 'text-green-400' :
                    msg.type === 'noteoff' ? 'text-red-400' :
                    msg.type === 'control' ? 'text-blue-400' :
                    msg.type === 'program' ? 'text-purple-400' :
                    msg.type === 'pitchbend' ? 'text-yellow-400' :
                    'text-gray-400'
                  ]"
                >
                  {{ msg.typeName }}
                </span>
                <span class="text-white">{{ msg.description }}</span>
              </div>
            </div>
          </div>
        </div>

        <!-- 虚拟 MIDI 键盘 -->
        <div class="tech-card mb-8">
          <h2 class="text-2xl font-semibold mb-6 text-white">虚拟 MIDI 键盘</h2>
          
          <div v-if="!selectedOutput" class="text-center py-8 text-gray-400">
            请先选择一个输出设备
          </div>
          
          <div v-else>
            <div class="bg-gray-800 rounded-lg p-6 mb-4">
              <div class="flex justify-center gap-1 mb-4 overflow-x-auto">
                <button
                  v-for="note in virtualKeyboard"
                  :key="note.number"
                  @mousedown="sendNoteOn(note.number)"
                  @mouseup="sendNoteOff(note.number)"
                  @mouseleave="sendNoteOff(note.number)"
                  @touchstart.prevent="sendNoteOn(note.number)"
                  @touchend.prevent="sendNoteOff(note.number)"
                  :class="[
                    note.isBlack 
                      ? 'bg-gray-900 text-white h-32 w-12 -mx-2 z-10' 
                      : 'bg-white text-black h-48 w-16',
                    activeNotes.has(note.number) ? 'opacity-60' : '',
                    'rounded-b-lg shadow-lg hover:opacity-80 transition-opacity flex items-end justify-center pb-2 text-xs font-semibold select-none'
                  ]"
                >
                  {{ note.name }}
                </button>
              </div>

              <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
                <div>
                  <label class="text-white text-sm mb-1 block">力度: {{ velocity }}</label>
                  <input
                    v-model.number="velocity"
                    type="range"
                    min="0"
                    max="127"
                    class="w-full"
                  >
                </div>

                <div>
                  <label class="text-white text-sm mb-1 block">通道: {{ midiChannel }}</label>
                  <input
                    v-model.number="midiChannel"
                    type="range"
                    min="1"
                    max="16"
                    class="w-full"
                  >
                </div>

                <div>
                  <label class="text-white text-sm mb-1 block">音色: {{ program }}</label>
                  <input
                    v-model.number="program"
                    type="range"
                    min="0"
                    max="127"
                    class="w-full"
                    @change="sendProgramChange"
                  >
                </div>

                <div>
                  <label class="text-white text-sm mb-1 block">八度: {{ octave }}</label>
                  <input
                    v-model.number="octave"
                    type="range"
                    min="-2"
                    max="2"
                    class="w-full"
                  >
                </div>
              </div>

              <div class="text-gray-400 text-sm text-center">
                使用鼠标或触摸操作虚拟键盘发送 MIDI 消息
              </div>
            </div>
          </div>
        </div>

        <!-- MIDI 控制器 -->
        <div class="tech-card mb-8">
          <h2 class="text-2xl font-semibold mb-6 text-white">MIDI 控制器</h2>
          
          <div v-if="!selectedOutput" class="text-center py-8 text-gray-400">
            请先选择一个输出设备
          </div>
          
          <div v-else class="bg-gray-800 rounded-lg p-6">
            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
              <!-- 常用控制器 -->
              <div
                v-for="controller in midiControllers"
                :key="controller.number"
                class="bg-gray-900 rounded-lg p-4"
              >
                <div class="flex items-center justify-between mb-2">
                  <label class="text-white font-semibold">{{ controller.name }}</label>
                  <span class="text-tech-accent">{{ controller.value }}</span>
                </div>
                <input
                  v-model.number="controller.value"
                  type="range"
                  min="0"
                  max="127"
                  class="w-full"
                  @input="sendControlChange(controller.number, controller.value)"
                >
                <div class="text-gray-400 text-xs mt-1">
                  CC {{ controller.number }}
                </div>
              </div>
            </div>

            <div class="mt-6">
              <h3 class="text-white font-semibold mb-3">弯音轮</h3>
              <input
                v-model.number="pitchBend"
                type="range"
                min="0"
                max="16383"
                class="w-full"
                @input="sendPitchBend"
              >
              <div class="text-gray-400 text-xs mt-1 text-center">
                当前值: {{ pitchBend }} (中心: 8192)
              </div>
            </div>
          </div>
        </div>

        <!-- MIDI 统计 -->
        <div class="tech-card mb-8">
          <h2 class="text-2xl font-semibold mb-6 text-white">MIDI 统计</h2>
          
          <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
            <div class="bg-gray-800 rounded-lg p-6 text-center">
              <div class="text-3xl font-bold text-blue-400 mb-2">{{ statistics.totalMessages }}</div>
              <div class="text-gray-400 text-sm">总消息数</div>
            </div>

            <div class="bg-gray-800 rounded-lg p-6 text-center">
              <div class="text-3xl font-bold text-green-400 mb-2">{{ statistics.noteOnCount }}</div>
              <div class="text-gray-400 text-sm">音符开始</div>
            </div>

            <div class="bg-gray-800 rounded-lg p-6 text-center">
              <div class="text-3xl font-bold text-red-400 mb-2">{{ statistics.noteOffCount }}</div>
              <div class="text-gray-400 text-sm">音符结束</div>
            </div>

            <div class="bg-gray-800 rounded-lg p-6 text-center">
              <div class="text-3xl font-bold text-purple-400 mb-2">{{ statistics.controlChangeCount }}</div>
              <div class="text-gray-400 text-sm">控制变化</div>
            </div>
          </div>
        </div>
      </template>

      <!-- API 信息 -->
      <div class="tech-card">
        <h3 class="text-xl font-semibold mb-4 text-white">API 信息</h3>
        <div class="space-y-4 text-gray-300">
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">浏览器支持</h4>
            <p>Chrome 43+, Edge 79+, Opera 30+</p>
            <p class="text-sm mt-1 text-yellow-400">注意：Firefox 和 Safari 目前不支持</p>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">核心 API</h4>
            <ul class="list-disc list-inside space-y-1">
              <li><code class="bg-gray-800 px-2 py-1 rounded">navigator.requestMIDIAccess()</code> - 请求 MIDI 访问权限</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">MIDIAccess.inputs</code> - 获取输入设备列表</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">MIDIAccess.outputs</code> - 获取输出设备列表</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">MIDIInput.onmidimessage</code> - 监听 MIDI 消息</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">MIDIOutput.send(data)</code> - 发送 MIDI 消息</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">MIDI 消息类型</h4>
            <ul class="list-disc list-inside space-y-1 text-sm">
              <li><strong>Note On (0x90):</strong> 音符开始，包含音符编号和力度</li>
              <li><strong>Note Off (0x80):</strong> 音符结束</li>
              <li><strong>Control Change (0xB0):</strong> 控制器变化，如音量、调制轮等</li>
              <li><strong>Program Change (0xC0):</strong> 音色/乐器变化</li>
              <li><strong>Pitch Bend (0xE0):</strong> 弯音变化</li>
              <li><strong>Aftertouch (0xD0):</strong> 触后压力</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">基本用法</h4>
            <pre class="bg-gray-800 p-4 rounded text-sm overflow-x-auto">
<span class="text-gray-500">// 请求 MIDI 访问</span>
<span class="text-blue-400">const</span> midiAccess = <span class="text-blue-400">await</span> navigator.requestMIDIAccess();

<span class="text-gray-500">// 监听输入</span>
<span class="text-blue-400">for</span> (<span class="text-blue-400">const</span> input <span class="text-blue-400">of</span> midiAccess.inputs.values()) {
  input.onmidimessage = (message) => {
    <span class="text-blue-400">const</span> [status, note, velocity] = message.data;
    console.log(<span class="text-green-400">`状态: ${status}, 音符: ${note}, 力度: ${velocity}`</span>);
  };
}

<span class="text-gray-500">// 发送 Note On 消息</span>
<span class="text-blue-400">const</span> output = midiAccess.outputs.values().next().value;
<span class="text-blue-400">const</span> noteOn = [<span class="text-orange-400">0x90</span>, <span class="text-orange-400">60</span>, <span class="text-orange-400">127</span>]; <span class="text-gray-500">// C4, 最大力度</span>
output.send(noteOn);</pre>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">MIDI 音符编号</h4>
            <div class="text-sm space-y-1">
              <p>MIDI 音符编号范围：0-127</p>
              <p>中央 C (C4) = 60</p>
              <p>计算公式：音符编号 = 12 × (八度 + 1) + 音高偏移</p>
              <p>例如：A4 (440Hz) = 69</p>
            </div>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">常用控制器编号</h4>
            <ul class="list-disc list-inside space-y-1 text-sm">
              <li>0 - Bank Select（音色库选择）</li>
              <li>1 - Modulation（调制轮）</li>
              <li>7 - Volume（音量）</li>
              <li>10 - Pan（声像）</li>
              <li>11 - Expression（表情）</li>
              <li>64 - Sustain Pedal（延音踏板）</li>
              <li>71 - Resonance（共鸣）</li>
              <li>74 - Cutoff（截止频率）</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">使用场景</h4>
            <ul class="list-disc list-inside space-y-1 text-sm">
              <li>数字音频工作站（DAW）</li>
              <li>在线音乐编辑器和合成器</li>
              <li>MIDI 乐器学习应用</li>
              <li>音乐游戏和互动体验</li>
              <li>DJ 控制台和混音应用</li>
              <li>乐器模拟器</li>
              <li>音乐可视化工具</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">最佳实践</h4>
            <ul class="list-disc list-inside space-y-1 text-sm">
              <li>始终检查浏览器是否支持 Web MIDI API</li>
              <li>妥善处理用户拒绝权限的情况</li>
              <li>监听设备连接和断开事件（statechange）</li>
              <li>发送 Note Off 确保音符正常结束</li>
              <li>使用时间戳精确控制 MIDI 消息时序</li>
              <li>注意 MIDI 消息的频率，避免过载</li>
              <li>提供无 MIDI 设备时的降级方案</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">安全性</h4>
            <div class="text-sm space-y-1">
              <p>Web MIDI API 需要用户明确授权才能访问 MIDI 设备。</p>
              <p>某些浏览器要求在 HTTPS 环境下才能使用此 API。</p>
              <p>建议在请求权限前向用户说明使用原因。</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

// 类型定义
interface MIDIDevice {
  id: string
  name: string
  manufacturer: string
  state: string
  type: string
}

interface MIDIMessage {
  timestamp: string
  type: string
  typeName: string
  description: string
}

interface MIDIController {
  number: number
  name: string
  value: number
}

interface VirtualKey {
  number: number
  name: string
  isBlack: boolean
}

interface Statistics {
  totalMessages: number
  noteOnCount: number
  noteOffCount: number
  controlChangeCount: number
}

// 响应式状态
const isSupported = ref(false)
const isRequesting = ref(false)
const accessError = ref('')
const midiAccess = ref<MIDIAccess | null>(null)

// 设备列表
const inputDevices = ref<MIDIDevice[]>([])
const outputDevices = ref<MIDIDevice[]>([])
const selectedOutput = ref<MIDIOutput | null>(null)

// MIDI 消息
const midiMessages = ref<MIDIMessage[]>([])
const maxMessages = 100

// 虚拟键盘
const virtualKeyboard = ref<VirtualKey[]>([
  { number: 60, name: 'C', isBlack: false },
  { number: 61, name: 'C#', isBlack: true },
  { number: 62, name: 'D', isBlack: false },
  { number: 63, name: 'D#', isBlack: true },
  { number: 64, name: 'E', isBlack: false },
  { number: 65, name: 'F', isBlack: false },
  { number: 66, name: 'F#', isBlack: true },
  { number: 67, name: 'G', isBlack: false },
  { number: 68, name: 'G#', isBlack: true },
  { number: 69, name: 'A', isBlack: false },
  { number: 70, name: 'A#', isBlack: true },
  { number: 71, name: 'B', isBlack: false }
])

const activeNotes = ref<Set<number>>(new Set())
const velocity = ref(100)
const midiChannel = ref(1)
const program = ref(0)
const octave = ref(0)

// MIDI 控制器
const midiControllers = ref<MIDIController[]>([
  { number: 1, name: '调制轮 (Modulation)', value: 0 },
  { number: 7, name: '音量 (Volume)', value: 100 },
  { number: 10, name: '声像 (Pan)', value: 64 },
  { number: 11, name: '表情 (Expression)', value: 127 },
  { number: 64, name: '延音踏板 (Sustain)', value: 0 },
  { number: 71, name: '共鸣 (Resonance)', value: 64 }
])

const pitchBend = ref(8192)

// 统计
const statistics = ref<Statistics>({
  totalMessages: 0,
  noteOnCount: 0,
  noteOffCount: 0,
  controlChangeCount: 0
})

// 初始化
onMounted(() => {
  isSupported.value = !!(navigator.requestMIDIAccess)
})

// 清理
onUnmounted(() => {
  if (midiAccess.value) {
    // 清理 MIDI 输入监听器
    for (const input of midiAccess.value.inputs.values()) {
      input.onmidimessage = null
      input.onstatechange = null
    }
  }
})

// 请求 MIDI 访问权限
const requestMIDIAccess = async () => {
  isRequesting.value = true
  accessError.value = ''

  try {
    midiAccess.value = await navigator.requestMIDIAccess()
    
    // 获取设备列表
    updateDeviceList()

    // 监听设备变化
    midiAccess.value.onstatechange = () => {
      updateDeviceList()
    }

    // 设置输入监听
    for (const input of midiAccess.value.inputs.values()) {
      input.onmidimessage = handleMIDIMessage
    }
  } catch (error) {
    console.error('MIDI 访问失败:', error)
    accessError.value = '无法访问 MIDI 设备，请检查浏览器权限设置'
  } finally {
    isRequesting.value = false
  }
}

// 更新设备列表
const updateDeviceList = () => {
  if (!midiAccess.value) return

  // 输入设备
  inputDevices.value = Array.from(midiAccess.value.inputs.values()).map(input => ({
    id: input.id,
    name: input.name || '未命名设备',
    manufacturer: input.manufacturer || '',
    state: input.state,
    type: input.type
  }))

  // 输出设备
  outputDevices.value = Array.from(midiAccess.value.outputs.values()).map(output => ({
    id: output.id,
    name: output.name || '未命名设备',
    manufacturer: output.manufacturer || '',
    state: output.state,
    type: output.type
  }))

  // 如果选中的输出设备断开，清除选择
  if (selectedOutput.value) {
    const stillConnected = Array.from(midiAccess.value.outputs.values())
      .some(output => output.id === selectedOutput.value?.id)
    
    if (!stillConnected) {
      selectedOutput.value = null
    }
  }
}

// 选择输出设备
const selectOutputDevice = (device: MIDIDevice) => {
  if (!midiAccess.value) return

  const output = Array.from(midiAccess.value.outputs.values())
    .find(o => o.id === device.id)

  if (output) {
    selectedOutput.value = output as MIDIOutput
  }
}

// 处理 MIDI 消息
const handleMIDIMessage = (message: MIDIMessageEvent) => {
  if (!message.data || message.data.length < 1) return
  
  const [status, data1, data2] = message.data
  const command = status & 0xf0
  const channel = (status & 0x0f) + 1

  let type = 'unknown'
  let typeName = '未知'
  let description = ''

  switch (command) {
    case 0x90:
      if (data2 > 0) {
        type = 'noteon'
        typeName = 'Note On'
        description = `通道 ${channel}, 音符 ${data1}, 力度 ${data2}`
        statistics.value.noteOnCount++
      } else {
        type = 'noteoff'
        typeName = 'Note Off'
        description = `通道 ${channel}, 音符 ${data1}`
        statistics.value.noteOffCount++
      }
      break

    case 0x80:
      type = 'noteoff'
      typeName = 'Note Off'
      description = `通道 ${channel}, 音符 ${data1}, 力度 ${data2}`
      statistics.value.noteOffCount++
      break

    case 0xb0:
      type = 'control'
      typeName = 'Control Change'
      description = `通道 ${channel}, CC ${data1}, 值 ${data2}`
      statistics.value.controlChangeCount++
      break

    case 0xc0:
      type = 'program'
      typeName = 'Program Change'
      description = `通道 ${channel}, 音色 ${data1}`
      break

    case 0xe0:
      type = 'pitchbend'
      typeName = 'Pitch Bend'
      const bendValue = (data2 << 7) | data1
      description = `通道 ${channel}, 值 ${bendValue}`
      break

    case 0xd0:
      type = 'aftertouch'
      typeName = 'Aftertouch'
      description = `通道 ${channel}, 压力 ${data1}`
      break
  }

  const timestamp = new Date().toLocaleTimeString('zh-CN', { 
    hour12: false,
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  } as any)

  midiMessages.value.push({
    timestamp,
    type,
    typeName,
    description
  })

  // 限制消息数量
  if (midiMessages.value.length > maxMessages) {
    midiMessages.value.shift()
  }

  statistics.value.totalMessages++
}

// 清空消息
const clearMessages = () => {
  midiMessages.value = []
}

// 发送 Note On
const sendNoteOn = (note: number) => {
  if (!selectedOutput.value) return

  const adjustedNote = note + (octave.value * 12)
  if (adjustedNote < 0 || adjustedNote > 127) return

  const channel = midiChannel.value - 1
  const noteOn = [0x90 | channel, adjustedNote, velocity.value]
  
  selectedOutput.value.send(noteOn)
  activeNotes.value.add(note)
}

// 发送 Note Off
const sendNoteOff = (note: number) => {
  if (!selectedOutput.value) return

  const adjustedNote = note + (octave.value * 12)
  if (adjustedNote < 0 || adjustedNote > 127) return

  const channel = midiChannel.value - 1
  const noteOff = [0x80 | channel, adjustedNote, 0]
  
  selectedOutput.value.send(noteOff)
  activeNotes.value.delete(note)
}

// 发送控制变化
const sendControlChange = (controller: number, value: number) => {
  if (!selectedOutput.value) return

  const channel = midiChannel.value - 1
  const controlChange = [0xb0 | channel, controller, value]
  
  selectedOutput.value.send(controlChange)
}

// 发送音色变化
const sendProgramChange = () => {
  if (!selectedOutput.value) return

  const channel = midiChannel.value - 1
  const programChange = [0xc0 | channel, program.value]
  
  selectedOutput.value.send(programChange)
}

// 发送弯音
const sendPitchBend = () => {
  if (!selectedOutput.value) return

  const channel = midiChannel.value - 1
  const lsb = pitchBend.value & 0x7f
  const msb = (pitchBend.value >> 7) & 0x7f
  const pitchBendMsg = [0xe0 | channel, lsb, msb]
  
  selectedOutput.value.send(pitchBendMsg)
}
</script>

<style scoped>
/* 自定义样式 */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  cursor: pointer;
}

input[type="range"]::-webkit-slider-track {
  background: #374151;
  height: 0.5rem;
  border-radius: 0.25rem;
}

input[type="range"]::-moz-range-track {
  background: #374151;
  height: 0.5rem;
  border-radius: 0.25rem;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: #3b82f6;
  cursor: pointer;
  margin-top: -0.375rem;
}

input[type="range"]::-moz-range-thumb {
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: #3b82f6;
  cursor: pointer;
  border: none;
}
</style>

